package noticeservice

import (
	"context"
	"fmt"
	"games.com/server/internal/pkg/config"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

var (
	insertNoticeSQL    = `INSERT INTO notice (gm, send_time, exit_time, content) VALUES (?, ?, ?, ?)`
	deleteNoticeSQL    = `DELETE FROM notice WHERE id = ?`
	updateNoticeSQL    = `UPDATE notice SET gm = ?, send_time = ?, exit_time = ?, content = ? WHERE id = ?`
	selectNoticeCntSQL = `SELECT count(1) FROM notice`
	selectNoticeSQL    = `SELECT id, gm, send_time, exit_time, content FROM notice LIMIT ?, ?`
	queryNoticeByIDSQL = `SELECT id, gm, send_time, exit_time, content FROM notice WHERE id = ?`
)

type noticeDAO struct {
	db *sqlx.DB
}

func NewNoticeDAO(config *config.Config) (*noticeDAO, error) {
	ad := &noticeDAO{}

	db, err := sqlx.Connect("mysql", config.Dsn)
	if err != nil {
		return nil, fmt.Errorf("failed to open mysql connection, dsn:%s, err:%w", config.Dsn, err)
	}

	ad.db = db
	return ad, nil
}

func (nd *noticeDAO) InsertNotice(ctx context.Context, notice *Notice) error {
	result, err := nd.db.ExecContext(ctx, insertNoticeSQL, notice.Gm, notice.SendTime, notice.ExitTime, notice.Content)
	if err != nil {
		return err
	}

	ID, err := result.LastInsertId()
	if err != nil {
		return err
	}

	notice.ID = int32(ID)

	return nil
}

func (nd *noticeDAO) DeleteNotice(ctx context.Context, ID int32) error {
	_, err := nd.db.ExecContext(ctx, deleteNoticeSQL, ID)
	if err != nil {
		return err
	}

	return nil
}

func (nd *noticeDAO) UpdateNotice(ctx context.Context, notice *Notice) error {
	_, err := nd.db.ExecContext(ctx, updateNoticeSQL, notice.Gm, notice.SendTime, notice.ExitTime, notice.Content, notice.ID)
	if err != nil {
		return err
	}

	return nil
}

func (nd *noticeDAO) QueryNoticeCnt(ctx context.Context) (int32, error) {
	var cnt int32

	err := nd.db.GetContext(ctx, &cnt, selectNoticeCntSQL)
	if err != nil {
		return cnt, err
	}

	return cnt, nil
}

func (nd *noticeDAO) QueryNotice(ctx context.Context, start, offset int32) ([]*Notice, error) {
	var notice []*Notice

	err := nd.db.SelectContext(ctx, &notice, selectNoticeSQL, start, offset)
	if err != nil {
		return nil, err
	}

	return notice, nil
}

func (nd *noticeDAO) QueryNoticeByID(ctx context.Context, id int32) (*Notice, error) {
	var n Notice

	err := nd.db.GetContext(ctx, &n, queryNoticeByIDSQL, id)
	if err != nil {
		return nil, err
	}

	return &n, nil
}
